home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / base / netkit-b.07a / netkit-b / NetKit-B-0.07A / arp / arp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-13  |  8.9 KB  |  400 lines

  1. /*
  2.  * Copyright (c) 1984 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Sun Microsystems, Inc.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. char copyright[] =
  39. "@(#) Copyright (c) 1984 Regents of the University of California.\n\
  40.  All rights reserved.\n";
  41. #endif /* not lint */
  42.  
  43. #ifndef lint
  44. /*static char sccsid[] = "from: @(#)arp.c    5.11.1.1 (Berkeley) 7/22/91";*/
  45. static char rcsid[] = "$Id: arp.c,v 1.3 1996/07/13 20:16:20 dholland Exp $";
  46. #endif /* not lint */
  47.  
  48. /*
  49.  * arp - display, set, and delete arp table entries
  50.  */
  51.  
  52. #include <sys/param.h>
  53. #include <sys/file.h>
  54. #include <sys/socket.h>
  55. #include <sys/ioctl.h>
  56.  
  57. #include <netdb.h>
  58. #include <netinet/in.h>
  59. #include <net/if.h>
  60. #include <linux/netdevice.h>
  61. #include <linux/if_arp.h>
  62.  
  63. #include <errno.h>
  64. #include <stdio.h>
  65. #include <paths.h>
  66.  
  67. extern int errno;
  68.  
  69. main(argc, argv)
  70.     int argc;
  71.     char **argv;
  72. {
  73.     int ch;
  74.  
  75.     while ((ch = getopt(argc, argv, "adsf")) != EOF)
  76.         switch((char)ch) {
  77.         case 'a': {
  78.             char *mem = 0;
  79.  
  80.             if (argc > 2)
  81.                 usage();
  82.             dump();
  83.             exit(0);
  84.         }
  85.         case 'd':
  86.             if (argc != 3)
  87.                 usage();
  88.             delete(argv[2]);
  89.             exit(0);
  90.         case 's':
  91.             if (argc < 4 || argc > 7)
  92.                 usage();
  93.             exit(set(argc-2, &argv[2]) ? 1 : 0);
  94.         case 'f':
  95.             if (argc != 3)
  96.                 usage();
  97.             exit (file(argv[2]) ? 1 : 0);
  98.         case '?':
  99.         default:
  100.             usage();
  101.         }
  102.     if (argc != 2)
  103.         usage();
  104.     get(argv[1]);
  105.     exit(0);
  106. }
  107.  
  108. /*
  109.  * Process a file to set standard arp entries
  110.  */
  111. file(name)
  112.     char *name;
  113. {
  114.     FILE *fp;
  115.     int i, retval;
  116.     char line[100], arg[5][50], *args[5];
  117.  
  118.     if ((fp = fopen(name, "r")) == NULL) {
  119.         fprintf(stderr, "arp: cannot open %s\n", name);
  120.         exit(1);
  121.     }
  122.     args[0] = &arg[0][0];
  123.     args[1] = &arg[1][0];
  124.     args[2] = &arg[2][0];
  125.     args[3] = &arg[3][0];
  126.     args[4] = &arg[4][0];
  127.     retval = 0;
  128.     while(fgets(line, 100, fp) != NULL) {
  129.         i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
  130.             arg[3], arg[4]);
  131.         if (i < 2) {
  132.             fprintf(stderr, "arp: bad line: %s\n", line);
  133.             retval = 1;
  134.             continue;
  135.         }
  136.         if (set(i, args))
  137.             retval = 1;
  138.     }
  139.     fclose(fp);
  140.     return (retval);
  141. }
  142.  
  143. /*
  144.  * Set an individual arp entry 
  145.  */
  146. set(argc, argv)
  147.     int argc;
  148.     char **argv;
  149. {
  150.     struct arpreq ar;
  151.     struct hostent *hp;
  152.     struct sockaddr_in *sin;
  153.     u_char *ea;
  154.     int s;
  155.     char *host = argv[0], *eaddr = argv[1];
  156.  
  157.     argc -= 2;
  158.     argv += 2;
  159.     bzero((caddr_t)&ar, sizeof ar);
  160.     sin = (struct sockaddr_in *)&ar.arp_pa;
  161.     sin->sin_family = AF_INET;
  162.     sin->sin_addr.s_addr = inet_addr(host);
  163.     if (sin->sin_addr.s_addr == -1) {
  164.         if (!(hp = gethostbyname(host))) {
  165.             fprintf(stderr, "arp: %s: ", host);
  166.             herror((char *)NULL);
  167.             return (1);
  168.         }
  169.         bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  170.             sizeof sin->sin_addr);
  171.     }
  172.     ea = (u_char *)ar.arp_ha.sa_data;
  173.     if (ether_aton(eaddr, ea))
  174.         return (1);
  175.     ar.arp_flags = ATF_PERM|ATF_COM;
  176.     while (argc-- > 0) {
  177.         if (strncmp(argv[0], "temp", 4) == 0)
  178.             ar.arp_flags &= ~ATF_PERM;
  179.         else if (strncmp(argv[0], "pub", 3) == 0)
  180.             ar.arp_flags |= ATF_PUBL;
  181.         else if (strncmp(argv[0], "trail", 5) == 0)
  182.             ar.arp_flags |= ATF_USETRAILERS;
  183.         argv++;
  184.     }
  185.     
  186.     s = socket(AF_INET, SOCK_DGRAM, 0);
  187.     if (s < 0) {
  188.         perror("arp: socket");
  189.         exit(1);
  190.     }
  191.     if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) {
  192.         perror(host);
  193.         exit(1);
  194.     }
  195.     close(s);
  196.     return (0);
  197. }
  198.  
  199. /*
  200.  * Display an individual arp entry
  201.  */
  202. get(host)
  203.     char *host;
  204. {
  205.     struct arpreq ar;
  206.     struct hostent *hp;
  207.     struct sockaddr_in *sin;
  208.     unsigned char *ea;
  209.     int s;
  210.  
  211.     bzero((caddr_t)&ar, sizeof ar);
  212.     ar.arp_pa.sa_family = AF_INET;
  213.     sin = (struct sockaddr_in *)&ar.arp_pa;
  214.     sin->sin_family = AF_INET;
  215.     sin->sin_addr.s_addr = inet_addr(host);
  216.     if ((long)sin->sin_addr.s_addr == -1) {
  217.         if (!(hp = gethostbyname(host))) {
  218.             fprintf(stderr, "arp: %s: ", host);
  219.             herror((char *)NULL);
  220.             exit(1);
  221.         }
  222.         bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  223.             sizeof sin->sin_addr);
  224.     }
  225.     s = socket(AF_INET, SOCK_DGRAM, 0);
  226.     if (s < 0) {
  227.         perror("arp: socket");
  228.         exit(1);
  229.     }
  230.     if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) {
  231.         if (errno == ENXIO)
  232.             printf("%s (%s) -- no entry\n",
  233.                 host, inet_ntoa(sin->sin_addr));
  234.         else
  235.             perror("SIOCGARP");
  236.         exit(1);
  237.     }
  238.     close(s);
  239.     ea = (u_char *)ar.arp_ha.sa_data;
  240.     printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
  241.     /* if (ar.arp_flags & ATF_COM)*/
  242.         ether_print(ea);
  243.     /* else
  244.         printf("(incomplete)"); */
  245.     if (ar.arp_flags & ATF_PERM)
  246.         printf(" permanent");
  247.     if (ar.arp_flags & ATF_PUBL)
  248.         printf(" published");
  249.     if (ar.arp_flags & ATF_USETRAILERS)
  250.         printf(" trailers");
  251.     printf("\n");
  252. }
  253.  
  254. /*
  255.  * Delete an arp entry 
  256.  */
  257. delete(host)
  258.     char *host;
  259. {
  260.     struct arpreq ar;
  261.     struct hostent *hp;
  262.     struct sockaddr_in *sin;
  263.     int s;
  264.  
  265.     bzero((caddr_t)&ar, sizeof ar);
  266.     ar.arp_pa.sa_family = AF_INET;
  267.     sin = (struct sockaddr_in *)&ar.arp_pa;
  268.     sin->sin_family = AF_INET;
  269.     sin->sin_addr.s_addr = inet_addr(host);
  270.     if ((long)sin->sin_addr.s_addr == -1) {
  271.         if (!(hp = gethostbyname(host))) {
  272.             fprintf(stderr, "arp: %s: ", host);
  273.             herror((char *)NULL);
  274.             exit(1);
  275.         }
  276.         bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  277.             sizeof sin->sin_addr);
  278.     }
  279.     s = socket(AF_INET, SOCK_DGRAM, 0);
  280.     if (s < 0) {
  281.         perror("arp: socket");
  282.         exit(1);
  283.     }
  284.     if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) {
  285.         if (errno == ENXIO)
  286.             printf("%s (%s) -- no entry\n",
  287.                 host, inet_ntoa(sin->sin_addr));
  288.         else
  289.             perror("SIOCDARP");
  290.         exit(1);
  291.     }
  292.     close(s);
  293.     printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
  294. }
  295.  
  296.  
  297. /*
  298.  * Dump the entire arp table
  299.  */
  300.  
  301. static unsigned long getipaddr(struct arpreq *at)
  302. {
  303.     return (* (long *)(at->arp_pa.sa_data));
  304. }
  305.  
  306. dump()
  307. {
  308.     extern int h_errno;
  309.     struct arpreq *at;
  310.     struct hostent *hp;
  311.     int bynumber, mf, arptab_size, sz;
  312.     int fd;
  313.     const char *host;
  314.  
  315.     sz = 65536;
  316.     at = (struct arpreq *)malloc((u_int)sz);
  317.     if (at == NULL) {
  318.         fputs("arp: can't get memory for arptab.\n", stderr);
  319.         exit(1);
  320.     }
  321.  
  322.     fd=open("/proc/net/arp",O_RDONLY,0);
  323.     if(fd==-1)
  324.     {
  325.         perror("arp: error opening arptab");
  326.         exit(1);
  327.     }
  328.     if((sz=read(fd,at,65536))<0)
  329.     {
  330.         perror("arp: error reading arptab");
  331.         exit(1);
  332.     }
  333.     arptab_size=sz/sizeof(struct arpreq);
  334.     close(fd);
  335.     for (bynumber = 0; arptab_size-- > 0; at++) {
  336.         unsigned long h_ip = getipaddr(at);
  337.         if (bynumber == 0)
  338.         {
  339.             struct in_addr ia;
  340.             ia.s_addr = h_ip;
  341.             hp = gethostbyaddr((const char *)&ia,
  342.                 sizeof(ia), AF_INET);
  343.         }
  344.         else
  345.             hp = 0;
  346.         if (hp)
  347.             host = hp->h_name;
  348.         else {
  349.             host = "?";
  350.             if (h_errno == TRY_AGAIN)
  351.                 bynumber = 1;
  352.         }
  353.         printf("%s (%s) at ", host, inet_ntoa(h_ip));
  354.         if (at->arp_flags & ATF_COM)
  355.             ether_print(at->arp_ha.sa_data);
  356.         else
  357.             printf("(incomplete)");
  358.         if (at->arp_flags & ATF_PERM)
  359.             printf(" permanent");
  360.         if (at->arp_flags & ATF_PUBL)
  361.             printf(" published");
  362.         if (at->arp_flags & ATF_USETRAILERS)
  363.             printf(" trailers");
  364.         printf("\n");
  365.     }
  366. }
  367.  
  368. ether_print(cp)
  369.     u_char *cp;
  370. {
  371.     printf("%02x:%02x:%02x:%02x:%02x:%02x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
  372. }
  373.  
  374. ether_aton(a, n)
  375.     char *a;
  376.     u_char *n;
  377. {
  378.     int i, o[6];
  379.  
  380.     i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
  381.                        &o[3], &o[4], &o[5]);
  382.     if (i != 6) {
  383.         fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
  384.         return (1);
  385.     }
  386.     for (i=0; i<6; i++)
  387.         n[i] = o[i];
  388.     return (0);
  389. }
  390.  
  391. usage()
  392. {
  393.     printf("usage: arp hostname\n");
  394.     printf("       arp -a\n");
  395.     printf("       arp -d hostname\n");
  396.     printf("       arp -s hostname ether_addr [temp] [pub] [trail]\n");
  397.     printf("       arp -f filename\n");
  398.     exit(1);
  399. }
  400.